package hapi.web;

#if php
import haxe.io.Bytes;
import php.Web;
import php.FileSystem;
import php.io.FileOutput;
import php.io.File;
#elseif neko
import neko.Web;
import neko.io.FileOutput;
import neko.FileSystem;
import neko.io.File;
#end

class FileUploadHandler {
	
	var parentPath:String;
	var namesConversion:String->String;
	var overrideExisting:Bool;
	var uploads:Hash<String>;
	var currOutput:FileOutput;
	
	public function new(parentPath:String, ?namesConversion:String->String, ?overrideExisting=false ) {
		if (namesConversion == null) this.namesConversion = noNameConvertion;
		this.parentPath = parentPath;
		this.overrideExisting = overrideExisting;
	}
	
	public function uploadMultipart() {
		this.uploads = new Hash<String>();
		Web.parseMultipart(onPart, onData);
		onFinish(uploads);
	}
	
	function onPart(part, file) {
		var fileName:String = namesConversion(file);
		var path = parentPath + "/" + fileName;
		if ( overrideExisting ) {
			if ( FileSystem.exists( path ) ) FileSystem.deleteFile( path );
		}else {
			
			if ( FileSystem.exists( path ) ) {
				var i = 1;
				var extension = path.substr(path.lastIndexOf( "." ) + 1);
				var noExtPath = path.substr(0, path.length - (extension.length + 1));
				var sufixedPath = noExtPath + "_" + i + "."+ extension;
				while ( FileSystem.exists(sufixedPath) ) {
					sufixedPath = noExtPath + "_" + i + "."+ extension;
					++i;
				}
				path = sufixedPath;
			}
		}
		this.uploads.set( part, path.substr( path.lastIndexOf("/")+1) );
		try {
			currOutput = File.write(path, true);
		}catch (e:Dynamic) {
			trace("could not open file <" + path + "> for writing");
			trace(e);
		}
	}
	
	function onData( data:Bytes, pos:Int, length:Int) {
		if ( currOutput != null) {
			#if php
			var buf = new StringBuf();
			buf.addSub( data.toString(), pos, length );
			currOutput.writeString(buf.toString());
			#elseif neko
			currOutput.writeBytes(data, pos, length);
			#end
		}
	}
	
	function noNameConvertion(name:String) {
		return name;
	}
	
	function checkTimeout() {
		
	}
	
	public dynamic function onFinish(uploaded:Hash<String>):Void;
	public dynamic function onPartUploaded(partName:String):Void;
}